package dir

//
import (
	"blot/base"
	"blot/config"
	"blot/structural"
	"bufio"
	"context"
	"github.com/fatih/color"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"
)

var (
	fuzzText []string
	DirHttp  *base.HTTPClient
	w        sync.WaitGroup
	url      = make(map[string][]any)
	l        sync.Mutex
	Ex       []string
	Status   []string
)

func dictionaryprocessing() []string {
	//处理输入的字典
	txts := strings.Split(structural.W, ";")
	return txts
}

func ReadDict() {
	//读取字典
	for _, txt := range dictionaryprocessing() {
		w.Add(1)
		go func() {
			defer w.Done()
			var txtlist []string
			file_data, err := os.OpenFile(txt, os.O_RDONLY, 0666)
			if err != nil {
				panic("读取错误")
			}
			defer func(file_data *os.File) {
				_ = file_data.Close()
			}(file_data)
			data := bufio.NewScanner(file_data)
			for data.Scan() {

				text := data.Text()
				if len(text) == 0 {
					continue
				}
				if len(structural.Ex) != 0 {
					for _, ex := range Ex {
						txtlist = append(txtlist, text+"."+ex)
					}
				} else {
					txtlist = append(txtlist, text)
				}
			}
			l.Lock()
			fuzzText = append(fuzzText, txtlist...)
			l.Unlock()

		}()
	}

}

var ch_distribution chan []string
var th_control chan int
var currrnt chan int

func distribution() {
	//分布式
	defer w.Done()

	n := 0
	bus_sum := 0
	business := len(fuzzText) / structural.T  //商
	remainder := len(fuzzText) % structural.T //余数
	for i := 1; i <= structural.T; i++ {
		w.Add(1)
		bus_sum = business + n
		th_control <- 1
		ch_distribution <- fuzzText[n:bus_sum]
		n += business
	}
	if remainder != 0 {
		w.Add(1)
		th_control <- 1
		ch_distribution <- fuzzText[bus_sum:]
	}
}

func Thread_starta(ctx context.Context) {
	//线程分发

	for {
		select {
		case data := <-ch_distribution:
			go processing(data)
		case <-signalChan:
			color.Red("[!]检测到强制中断，正在中断.....")
			config.HtmlData.Dir = url
			config.Create_html(structural.I, structural.URL.Url, 2)
			os.Exit(1)

		case <-ctx.Done():
			return
		}
	}
}

func progress(ctx context.Context) {

	for {
		select {
		case <-currrnt:

			bar.Load()
		case <-ctx.Done():
			return
		}
	}
}
func processing(data []string) {
	defer w.Done()
	var text []byte
	var code int
	var header http.Header
	var requesturl string
	var codezie []any
	var textlenght int
	var err error

	for _, value := range data {
		t := time.NewTimer(time.Duration(structural.Sleep) * time.Second)
		codezie = codezie[:0]
		if ok := strings.HasPrefix(value, "/"); ok {
			requesturl = structural.URL.Url + value
			text, code, header, err = DirHttp.Request(requesturl, structural.Body{})
		} else {
			requesturl = structural.URL.Url + "/" + value
			text, code, header, err = DirHttp.Request(requesturl, structural.Body{})
		}
		currrnt <- 1
		if err != nil {
			continue
		}
		<-t.C
		for _, status := range Status {
			if strconv.Itoa(code) == status {
				goto skip
			}
		}
		continue
	skip:
		textlenght = len(string(text))
		if structural.Filter > 0 && structural.Filter == textlenght {
			return
		}
		codezie = append(codezie, code, textlenght)
		if ok := strings.HasPrefix(strconv.Itoa(code), "3"); ok {
			//fmt.Println(header)

			codezie = append(codezie, header["Location"])

		}
		l.Lock()
		url[requesturl] = codezie
		l.Unlock()
	}
	<-th_control

}

var signalChan = make(chan os.Signal, 1)
var bar *base.Bar

func StartDir() {

	ctx, chf := context.WithCancel(context.Background())
	//defer chf()
	//go Thread_starta(ctx)
	ch_distribution = make(chan []string, structural.T)
	th_control = make(chan int, structural.T)
	currrnt = make(chan int, structural.T)
	signal.Notify(signalChan, syscall.SIGINT)

	ReadDict()
	w.Wait()
	bar = base.NewBar(len(fuzzText))
	w.Add(1)
	go distribution()
	go progress(ctx)
	go Thread_starta(ctx)

	w.Wait()
	chf()
	config.HtmlData.Dir = url
	config.Create_html(structural.I, structural.URL.Url, 2)

}
